package com.sj.proxy;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class Proxy2 {

    //用来产生新的代理类的对象
    public static Object newProxyInstance(Class infce) throws Exception {
        String rt = "\r\n";
        String methodStr = "";

        Method[] methods = infce.getMethods();
        for (Method m : methods) {
            methodStr +=
                    "    public void " + m.getName() + "() {" + rt +
                            "        long start = System.currentTimeMillis();" + rt +
                            "        System.out.println(\"starttime: \" + start);" + rt +
                            "        t." + m.getName() + "();" + rt +
                            "        long end = System.currentTimeMillis();" + rt +
                            "        System.out.println(\"time: \" + (end - start));" + rt +
                            "    }" + rt;
        }

        String src = "package com.sj.proxy;" + rt +
                "public class TankTimeProxy implements " + infce.getName() + " {" + rt +
                "    private Moveable t;" + rt +

                "    public TankTimeProxy(Moveable t) {" + rt +
                "        this.t = t;" + rt +
                "    }" + rt +
                methodStr +
                "}";

//        String fileUrl = System.getProperty("user.dir") + "/src/main/java/com/sj/proxy";
        //user.dir：当前项目的根路径
        //先把源代码写到下面
//        String fileName = fileUrl + "/TankTimeProxy.java";
        String fileName = "d:/src/com/sj/proxy/TankTimeProxy.java";
        File file = new File(fileName);
        FileWriter fileWriter = new FileWriter(file);
        fileWriter.write(src);
        fileWriter.flush();
        fileWriter.close();

        //在程序中编译这段代码
        //JavaCompiler java编译器
        //ToolProvider.getSystemJavaCompiler() 拿到系统当前默认的java编译器，其实就是javac
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager javaFileManager = compiler.getStandardFileManager(null, null, null);                                //通过javaFileManager管理要编译的文件
        Iterable<? extends JavaFileObject> compilationUnits = javaFileManager.getJavaFileObjects(fileName);                         //拿到编译的内容
        JavaCompiler.CompilationTask compilationTask = compiler.getTask(null, javaFileManager, null, null, null, compilationUnits); //编译的任务
        compilationTask.getClass();                                                                                                 //编译
        javaFileManager.close();

        //生成了这个TankTimeProxy.class之后，将期load到内存，并且生成一个对象
//        URL[] urls = new URL[]{new URL("file:/" + fileUrl)};
        URL[] urls = new URL[] {new URL("file:/" + "d:/src/")};
        URLClassLoader urlClassLoader = new URLClassLoader(urls);
        Class clazz = urlClassLoader.loadClass("com.sj.proxy.TankTimeProxy");
        //clazz.newInstance();//调用的是类的参数为空的构造方法，但是类中没有此构造方法。
        //站在java虚拟机的角度，每一个类、每一个类里面的每一个方法都是一个对象。
        Constructor constructor = clazz.getConstructor(infce);
        Object m = constructor.newInstance(new Tank());

        return m;
    }
}
